
package org.jeecgframework.poi.excel.export.base;

import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.properties.config.JeecgPropertyConfig;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecgframework.core.util.ApplicationContextUtil;
import org.jeecgframework.dict.service.AutoPoiDictServiceI;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecgframework.poi.excel.annotation.ExcelCollection;
import org.jeecgframework.poi.excel.annotation.ExcelEntity;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
import org.jeecgframework.poi.handler.inter.IExcelDataHandler;
import org.jeecgframework.poi.util.PoiPublicUtil;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

public class ExportBase {
    protected IExcelDataHandler dataHanlder;
    protected List<String> needHanlderList;

    protected JeecgPropertyConfig jeecgPropertyConfig;

    @PostConstruct
    public void init(){
        if (jeecgPropertyConfig == null){
            jeecgPropertyConfig = (JeecgPropertyConfig) SpringContextUtils.getBean("jeecgPropertyConfig");
        }
    }

    public ExportBase() {
    }

    private ExcelExportEntity createExcelExportEntity(Field field, String targetId, Class<?> pojoClass, List<Method> getMethods) throws Exception {
        Excel excel = (Excel) field.getAnnotation(Excel.class);
        ExcelExportEntity excelEntity = new ExcelExportEntity();
        excelEntity.setType(excel.type());
        this.getExcelField(targetId, field, excelEntity, excel, pojoClass);
        if (getMethods != null) {
            List<Method> newMethods = new ArrayList();
            newMethods.addAll(getMethods);
            newMethods.add(excelEntity.getMethod());
            excelEntity.setMethods(newMethods);
        }

        return excelEntity;
    }

    private Object formatValue(Object value, ExcelExportEntity entity) throws Exception {
        Date temp = null;
        SimpleDateFormat format;
        if (value instanceof String) {
            format = new SimpleDateFormat(entity.getDatabaseFormat());
            temp = format.parse(value.toString());
        } else if (value instanceof Date) {
            temp = (Date) value;
        }

        if (temp != null) {
            format = new SimpleDateFormat(entity.getFormat());
            value = format.format(temp);
        }

        return value;
    }

    public void getAllExcelField(String[] exclusions, String targetId, Field[] fields, List<ExcelExportEntity> excelParams, Class<?> pojoClass, List<Method> getMethods) throws Exception {
        List<String> exclusionsList = exclusions != null ? Arrays.asList(exclusions) : null;

        LoginUser sysUser = JwtUtil.getLoginUser();
        for (int i = 0; i < fields.length; ++i) {
            Field field = fields[i];
            if (!PoiPublicUtil.isNotUserExcelUserThis(exclusionsList, field, targetId)) {
                if (jeecgPropertyConfig == null){
                    jeecgPropertyConfig = (JeecgPropertyConfig) SpringContextUtils.getBean("jeecgPropertyConfig");
                }
                if (!jeecgPropertyConfig.getBaseDepartId().equalsIgnoreCase(sysUser.getCurrentCompanyId()) && field.getName().equalsIgnoreCase("companyId")) {
                    continue;
                }
                if (field.getAnnotation(Excel.class) != null) {
                    excelParams.add(this.createExcelExportEntity(field, targetId, pojoClass, getMethods));
                } else if (PoiPublicUtil.isCollection(field.getType())) {
                    ExcelCollection excel = (ExcelCollection) field.getAnnotation(ExcelCollection.class);
                    ParameterizedType pt = (ParameterizedType) field.getGenericType();
                    Class<?> clz = (Class) pt.getActualTypeArguments()[0];
                    List<ExcelExportEntity> list = new ArrayList();
                    this.getAllExcelField(exclusions, StringUtils.isNotEmpty(excel.id()) ? excel.id() : targetId, PoiPublicUtil.getClassFields(clz), list, clz, (List) null);
                    ExcelExportEntity excelEntity = new ExcelExportEntity();
                    excelEntity.setName(this.getExcelName(excel.name(), targetId));
                    excelEntity.setOrderNum(this.getCellOrder(excel.orderNum(), targetId));
                    excelEntity.setMethod(PoiPublicUtil.getMethod(field.getName(), pojoClass));
                    excelEntity.setList(list);
                    excelParams.add(excelEntity);
                } else {
                    List<Method> newMethods = new ArrayList();
                    if (getMethods != null) {
                        newMethods.addAll(getMethods);
                    }

                    newMethods.add(PoiPublicUtil.getMethod(field.getName(), pojoClass));
                    ExcelEntity excel = (ExcelEntity) field.getAnnotation(ExcelEntity.class);
                    this.getAllExcelField(exclusions, StringUtils.isNotEmpty(excel.id()) ? excel.id() : targetId, PoiPublicUtil.getClassFields(field.getType()), excelParams, field.getType(), newMethods);
                }
            }
        }

    }

    public int getCellOrder(String orderNum, String targetId) {
        if (!this.isInteger(orderNum) && targetId != null) {
            String[] arr = orderNum.split(CommonConstant.DEFAULT_SEPARATOR);
            String[] var5 = arr;
            int var6 = arr.length;

            for (int var7 = 0; var7 < var6; ++var7) {
                String str = var5[var7];
                String[] temp = str.split("_");
                if (targetId.equals(temp[1])) {
                    return Integer.valueOf(temp[0]);
                }
            }

            return 0;
        } else {
            return Integer.valueOf(orderNum);
        }
    }

    public Object getCellValue(ExcelExportEntity entity, Object obj) throws Exception {
        Object value;
        if (obj instanceof Map) {
            value = ((Map) obj).get(entity.getKey());
        } else {
            value = entity.getMethods() != null ? this.getFieldBySomeMethod(entity.getMethods(), obj) : entity.getMethod().invoke(obj);
        }

        if (StringUtils.isNotEmpty(entity.getNumFormat()) && value != null) {
            value = (new DecimalFormat(entity.getNumFormat())).format(value);
        }

        if (StringUtils.isNotEmpty(entity.getFormat())) {
            value = this.formatValue(value, entity);
        }

        if (entity.getReplace() != null && entity.getReplace().length > 0) {
            if (value == null) {
                value = "";
            }

            if (entity.isMultiReplace()) {
                value = this.multiReplaceValue(entity.getReplace(), String.valueOf(value));
            } else {
                value = this.replaceValue(entity.getReplace(), String.valueOf(value));
            }
        }

        if (this.needHanlderList != null && this.needHanlderList.contains(entity.getName())) {
            value = this.dataHanlder.exportHandler(obj, entity.getName(), value);
        }

        if (StringUtils.isNotEmpty(entity.getSuffix()) && value != null) {
            value = value + entity.getSuffix();
        }

        return value == null ? "" : value.toString();
    }

    public Collection<?> getListCellValue(ExcelExportEntity entity, Object obj) throws Exception {
        Object value;
        if (obj instanceof Map) {
            value = ((Map) obj).get(entity.getKey());
        } else {
            value = (Collection) entity.getMethod().invoke(obj);
        }

        return (Collection) value;
    }

    private void getExcelField(String targetId, Field field, ExcelExportEntity excelEntity, Excel excel, Class<?> pojoClass) throws Exception {
        excelEntity.setName(this.getExcelName(excel.name(), targetId));
        excelEntity.setWidth(excel.width());
        excelEntity.setHeight(excel.height());
        excelEntity.setNeedMerge(excel.needMerge());
        excelEntity.setMergeVertical(excel.mergeVertical());
        excelEntity.setMergeRely(excel.mergeRely());
        excelEntity.setReplace(excel.replace());
        excelEntity.setPullDown(excel.pullDown());
        if (StringUtils.isNotEmpty(excel.dicCode()) && excelEntity.getReplace() != null ) {
            AutoPoiDictServiceI jeecgDictService = null;

            try {
                jeecgDictService = (AutoPoiDictServiceI) ApplicationContextUtil.getContext().getBean(AutoPoiDictServiceI.class);
            } catch (Exception var8) {
            }

            if (jeecgDictService != null) {
                String[] dictReplace = jeecgDictService.queryDict(excel.dictTable(), excel.dicCode(), excel.dicText(), excel.dicKey());
                if (dictReplace != null && dictReplace.length != 0) {
                    excelEntity.setReplace(dictReplace);
                }

                //如果是字典表的数据添加 && !"zcgl_asset_info_sub".equalsIgnoreCase(excel.dictTable())
                if (excel.pullDown() && dictReplace != null && dictReplace.length != 0 && (StringUtils.isBlank(excel.dictTable()) || dictReplace.length < 100)) {

                    List<String> old = new ArrayList<>();
                    for (String r : dictReplace) {
                        old.add(r.substring(0, r.lastIndexOf("_")));
                    }
                    excelEntity.setOldReplace(old.toArray(new String[]{}));
                    String replaceKey = field.getName();
                    if (StringUtils.isNotBlank(excel.dictTable())){
                        replaceKey += "_" + excel.dictTable();
                    }
                    excelEntity.setReplaceKey(replaceKey);
                }
            }
        }

        excelEntity.setOrderNum(this.getCellOrder(excel.orderNum(), targetId));
        excelEntity.setWrap(excel.isWrap());
        excelEntity.setExportImageType(excel.imageType());
        excelEntity.setSuffix(excel.suffix());
        excelEntity.setDatabaseFormat(excel.databaseFormat());
        excelEntity.setFormat(StringUtils.isNotEmpty(excel.exportFormat()) ? excel.exportFormat() : excel.format());
        excelEntity.setStatistics(excel.isStatistics());
        String fieldname = field.getName();
        excelEntity.setKey(fieldname);
        excelEntity.setNumFormat(excel.numFormat());
        excelEntity.setMethod(PoiPublicUtil.getMethod(fieldname, pojoClass, excel.exportConvert()));
        excelEntity.setMultiReplace(excel.multiReplace());
        if (StringUtils.isNotEmpty(excel.groupName())) {
            excelEntity.setGroupName(excel.groupName());
            excelEntity.setColspan(true);
        }

    }

    public String getExcelName(String exportName, String targetId) {
        if (exportName.indexOf(",") >= 0 && targetId != null) {
            String[] arr = exportName.split(CommonConstant.DEFAULT_SEPARATOR);
            String[] var4 = arr;
            int var5 = arr.length;

            for (int var6 = 0; var6 < var5; ++var6) {
                String str = var4[var6];
                if (str.indexOf(targetId) != -1) {
                    return str.split("_")[0];
                }
            }

            return null;
        } else {
            return exportName;
        }
    }

    public Object getFieldBySomeMethod(List<Method> list, Object t) throws Exception {
        Method m;
        for (Iterator var3 = list.iterator(); var3.hasNext(); t = m.invoke(t)) {
            m = (Method) var3.next();
            if (t == null) {
                t = "";
                break;
            }
        }

        return t;
    }

    public short getRowHeight(List<ExcelExportEntity> excelParams) {
        double maxHeight = 0.0D;

        for (int i = 0; i < excelParams.size(); ++i) {
            maxHeight = maxHeight > ((ExcelExportEntity) excelParams.get(i)).getHeight() ? maxHeight : ((ExcelExportEntity) excelParams.get(i)).getHeight();
            if (((ExcelExportEntity) excelParams.get(i)).getList() != null) {
                for (int j = 0; j < ((ExcelExportEntity) excelParams.get(i)).getList().size(); ++j) {
                    maxHeight = maxHeight > ((ExcelExportEntity) ((ExcelExportEntity) excelParams.get(i)).getList().get(j)).getHeight() ? maxHeight : ((ExcelExportEntity) ((ExcelExportEntity) excelParams.get(i)).getList().get(j)).getHeight();
                }
            }
        }

        return (short) ((int) (maxHeight * 50.0D));
    }

    public boolean isInteger(String value) {
        try {
            Integer.parseInt(value);
            return true;
        } catch (NumberFormatException var3) {
            return false;
        }
    }

    private Object replaceValue(String[] replace, String value) {
        String[] var4 = replace;
        int var5 = replace.length;

        for (int var6 = 0; var6 < var5; ++var6) {
            String str = var4[var6];
            String[] temp = str.split("_");
            if (value.equals(temp[1])) {
                value = temp[0];
                break;
            }
        }

        return value;
    }

    private Object multiReplaceValue(String[] replace, String value) {
        if (value.indexOf(",") <= 0) {
            return this.replaceValue(replace, value);
        } else {
            String[] radioVals = value.split(CommonConstant.DEFAULT_SEPARATOR);
            String result = "";

            for (int i = 0; i < radioVals.length; ++i) {
                String radio = radioVals[i];
                String[] var8 = replace;
                int var9 = replace.length;

                for (int var10 = 0; var10 < var9; ++var10) {
                    String str = var8[var10];
                    String[] temp = str.split("_");
                    if (radio.equals(temp[1])) {
                        result = result.concat(temp[0]) + ",";
                        break;
                    }
                }
            }

            if (result.equals("")) {
                result = value;
            } else {
                result = result.substring(0, result.length() - 1);
            }

            return result;
        }
    }

    public void sortAllParams(List<ExcelExportEntity> excelParams) {
        Collections.sort(excelParams);
        Iterator var2 = excelParams.iterator();

        while (var2.hasNext()) {
            ExcelExportEntity entity = (ExcelExportEntity) var2.next();
            if (entity.getList() != null) {
                Collections.sort(entity.getList());
            }
        }

    }

    public void reConfigExcelExportParams(List<ExcelExportEntity> excelParams, ExportParams exportParams) {
        new HashSet();
        Map<String, List<String>> groupAndColumnList = new HashMap();
        Map<String, Integer> groupOrder = new HashMap();
        int index = -99;
        Iterator var7 = excelParams.iterator();

        while (var7.hasNext()) {
            ExcelExportEntity entity = (ExcelExportEntity) var7.next();
            if (entity.getOrderNum() == 0) {
                entity.setOrderNum(index++);
            }

            if (entity.getExportImageType() == 3) {
                entity.setImageBasePath(exportParams.getImageBasePath());
            }

            if (entity.getList() != null) {
                entity.getList().stream().forEach(e -> {
                    if (e.getExportImageType() == 3) {
                        e.setImageBasePath(exportParams.getImageBasePath());
                    }
                });
                Collections.sort(entity.getList());
            }

            String groupName = entity.getGroupName();
            if (StringUtils.isNotEmpty(groupName)) {
                List<String> ls = (List) groupAndColumnList.get(groupName);
                if (ls == null) {
                    ls = new ArrayList();
                    groupAndColumnList.put(groupName, ls);
                }

                ((List) ls).add(entity.getKey().toString());
                Integer order = (Integer) groupOrder.get(groupName);
                if (order == null || entity.getOrderNum() < order) {
                    order = entity.getOrderNum();
                }

                groupOrder.put(groupName, order);
            }
        }

        var7 = groupAndColumnList.keySet().iterator();

        while (var7.hasNext()) {
            String key = (String) var7.next();
            ExcelExportEntity temp = new ExcelExportEntity(key);
            temp.setColspan(true);
            temp.setSubColumnList((List) groupAndColumnList.get(key));
            temp.setOrderNum((Integer) groupOrder.get(key));
            excelParams.add(temp);
        }

        Collections.sort(excelParams);
    }
}
